home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Power Programmierung
/
Power-Programmierung (Tewi)(1994).iso
/
magazine
/
nan_news
/
toolkit
/
tmenu.asm
< prev
next >
Wrap
Assembly Source File
|
1991-08-15
|
39KB
|
748 lines
; File......: TMENU.ASM
; Author....: Ted Means
; Date......: $Date: 15 Aug 1991 23:07:14 $
; Revision..: $Revision: 1.2 $
; Log file..: $Logfile: E:/nanfor/src/tmenu.asv $
;
; This is an original work by Ted Means and is placed in the
; public domain.
;
; Modification history:
; ---------------------
;
; $Log: E:/nanfor/src/tmenu.asv $
;
; Rev 1.2 15 Aug 1991 23:07:14 GLENN
; Forest Belt proofread/edited/cleaned up doc
;
; Rev 1.1 14 Jun 1991 19:55:00 GLENN
; Minor edit to file header
;
; Rev 1.0 01 Apr 1991 01:03:56 GLENN
; Nanforum Toolkit
;
; This source code is used by Toolkit sources ATPROMPT.PRG and
; MENUTO.PRG. Look at that code for details on the TMENU system.
; This code depends on "TMENU.INC"
;
IDEAL
Public __ftprompt, __ftmenuto
Include "TMENU.INC"
Extrn __ParInfa:Far
Extrn __ParCLen:Far
Extrn __ParC:Far
Extrn __ParNI:Far
Extrn __RetNL:Far
Extrn __Ret:Far
Extrn __XGrab:Far
Extrn __XFree:Far
Extrn __XUnlock:Far
Segment _MenuData Word "DATA"
PrCount DW 0
Label HeadPtr DWord ; Pointer to head of linked list
HeadOfs DW 0 ; of menu items
HeadSeg DW 0
Ends _MenuData
Segment _NanFor Word "CODE"
Assume CS:_NanFor,ES:_MenuData
Proc __ftprompt Far
NewItem: Mov AX,42 ; Specify size of menu item
Push AX ; Put on stack
Call __XGrab ; Allocate RAM for it
Add SP,2 ; Realign stack
Mov BX,_MenuData ; Load local data segment
Mov ES,BX ; Now put it in a segment reg
Inc [ES:PrCount] ; Increment prompt counter
Push [ES:PrCount] ; We'll need it later
XChg AX,[ES:HeadOfs] ; Swap offsets
XChg DX,[ES:HeadSeg] ; Swap segments
LES BX,[ES:HeadPtr] ; Get pointer to new item
Mov [MenuItem.NextOfs],AX ; Move old head pointer to newly
Mov [MenuItem.NextSeg],DX ; allocated menu item
GetInfo: Pop [MenuItem.PrNum] ; Get prompt counter back
Push BP ; Save BP
Mov BP,SP ; Set up stack reference
Sub SP,4 ; Allocate local storage
Mov [NodeOfs],BX ; Save pointer in ES:BX in local
Mov [NodeSeg],ES ; storage -- avoids constant
; pushing and popping
Mov AX,1 ; Specify first parameter
Push AX ; Put on stack
Call __ParNI ; Get prompt location
Add SP,2 ; Realign stack
LES BX,[NodePtr] ; Restore node pointer
Mov [MenuItem.PrLoc],AX ; Store prompt location
Mov AX,2 ; Specify second parameter
Push AX ; Put on stack
Call __ParClen ; Get length
Add SP,2 ; Realign stack
Push AX ; Put length on stack
Call __XGrab ; Allocate RAM for copy
Push DX ; Put copy pointer on stack for
Push AX ; call to _ftStrDup
Mov AX,2 ; Specify second parmeter
Push AX ; Put on stack
Call __ParC ; Get pointer to prompt
Add SP,2 ; Realign stack
Push DX ; Put prompt pointer on stack
Push AX ; for call to _ftStrDup
Call _ftStrDup ; Copy the prompt string
Add SP,4 ; Realign stack
LES BX,[NodePtr] ; Restore node pointer
Pop [MenuItem.PrOfs] ; Store prompt offset
Pop [MenuItem.PrSeg] ; Store prompt offset
Pop [MenuItem.PrLen] ; Store prompt length
Call __XUnlock ; Tell VMM it's okay to let go
Mov AX,3 ; Specify third parmeter
Push AX ; Put on stack
Call __ParNI ; Get prompt attribute
Add SP,2 ; Realign stack
LES BX,[NodePtr] ; Restore node pointer
Mov [MenuItem.PrAtt],AL ; Store attribute
Mov AX,4 ; Specify fourth parameter
Push AX ; Put on stack
Call __ParNI ; Get message location
Add SP,2 ; Realign stack
LES BX,[NodePtr] ; Restore node pointer
Mov [MenuItem.MsgLoc],AX ; Store location
Mov AX,5 ; Specify fifth parameter
Push AX ; Put on stack
Call __ParClen ; Get length
Add SP,2 ; Realign stack
Push AX ; Put length on stack
Call __XGrab ; Allocate RAM for copy
Push DX ; Put copy pointer on stack for
Push AX ; call to _ftStrDup
Mov AX,5 ; Specify fifth parmeter
Push AX ; Put on stack
Call __ParC ; Get pointer to message
Add SP,2 ; Realign stack
Push DX ; Put message pointer on stack
Push AX ; for call to _ftStrDup
Call _ftStrDup ; Copy the prompt string
Add SP,4 ; Realign stack
LES BX,[NodePtr] ; Restore node pointer
Pop [MenuItem.MsgOfs] ; Store message offset
Pop [MenuItem.MsgSeg] ; Store message segment
Pop [MenuItem.MsgLen] ; Store message length
Call __XUnlock ; Tell VMM it's okay to let go
LES BX,[NodePtr] ; Restore node pointer
Mov AX,[MenuItem.MsgLen] ; Get message length
SHL AX,1 ; Multiply by two
Push AX ; Put buffer size on stack
Call __XGrab ; Allocate buffer
Add SP,2 ; Realign stack
LES BX,[NodePtr] ; Restore node pointer
Mov [MenuItem.BufOfs],AX ; Store buffer offset
Mov [MenuItem.BufSeg],DX ; Store buffer segment
Mov AX,6 ; Specify sixth parmeter
Push AX ; Put on stack
Call __ParNI ; Get message attribute
Add SP,2 ; Realign stack
LES BX,[NodePtr] ; Restore node pointer
Mov [MenuItem.MsgAtt],AL ; Store attribute
Mov AX,7 ; Specify seventh parameter
Push AX ; Save on stack
Call __ParNI ; Get hotkey attribute
Add SP,2 ; Realign stack
LES BX,[NodePtr] ; Restore node pointer
Mov [MenuItem.HKeyAtt],AL ; Store hotkey attribute
Mov AX,8 ; Specify eighth parameter
Push AX ; Save on stack
Call __ParNI ; Get hotkey location
Add SP,2 ; Realign stack
LES BX,[NodePtr] ; Restore node pointer
Mov [MenuItem.HKeyLoc],AX ; Store hotkey location
Mov AX,9 ; Specify ninth parameter
Push AX ; Save on stack
Call __ParNI ; Get light bar attribute
Add SP,2 ; Realign stack
LES BX,[NodePtr] ; Restore node pointer
Mov [MenuItem.HKeyVal],AL ; Store hotkey value
Mov AX,10 ; Specify tenth parameter
Push AX ; Save on stack
Call __ParNI ; Get light bar attribute
Add SP,2 ; Realign stack
LES BX,[NodePtr] ; Restore node pointer
Mov [MenuItem.LBarAtt],AL ; Store light bar attribute
Mov AX,11 ; Specify eleventh parameter
Push AX ; Save on stack
Call __ParNI ; Get hotkey/lightbar attribute
Add SP,2 ; Realign stack
LES BX,[NodePtr] ; Restore node pointer
Mov [MenuItem.LBHKAtt],AL ; Store hotkey/lightbar attribute
Mov AX,12 ; Specify twelfth parameter
Push AX ; Save on stack
Call __ParNI ; Get up arrow target
Add SP,2 ; Realign stack
LES BX,[NodePtr] ; Restore node pointer
Mov [MenuItem.Up],AX ; Store up arrow target
Mov AX,13 ; Specify thirteenth parameter
Push AX ; Save on stack
Call __ParNI ; Get down arrow target
Add SP,2 ; Realign stack
LES BX,[NodePtr] ; Restore node pointer
Mov [MenuItem.Down],AX ; Store down arrow target
Mov AX,14 ; Specify fourteenth parameter
Push AX ; Save on stack
Call __ParNI ; Get right arrow target
Add SP,2 ; Realign stack
LES BX,[NodePtr] ; Restore node pointer
Mov [MenuItem.Right],AX ; Store right arrow target
Mov AX,15 ; Specify fifteenth parameter
Push AX ; Save on stack
Call __ParNI ; Get left arrow target
Add SP,2 ; Realign stack
LES BX,[NodePtr] ; Restore node pointer
Mov [MenuItem.Left],AX ; Store left arrow target
Call __Ret ; Return NIL
Mov SP,BP ; Restore SP
Pop BP ; Restore BP
Ret
Endp __ftprompt
Proc _ftStrDup Near
Push BP ; Save BP
Mov BP,SP ; Set up stack reference
Push DS ; Save DS
Push SI ; Save SI
Push DI ; Save DI
CLD ; Ensure forward movement
Mov SI,[Word Ptr BP + 4] ; Get source offset
Mov DS,[Word Ptr BP + 6] ; Get source segment
Mov DI,[Word Ptr BP + 8] ; Get target offset
Mov ES,[Word Ptr BP + 10] ; Get target segment
Mov CX,[Word Ptr BP + 12] ; Get string length
Rep Movsb ; Copy string
Pop DI ; Restore DI
Pop SI ; Restore SI
Pop DS ; Restore DS
Pop BP ; Restore BP
Ret
Endp _ftStrDup
Proc __ftMenuTo Far
Push BP ; Save BP
Mov BP,SP ; Set up stack reference
Sub SP,24 ; Allocate space for locals
Mov BX,_MenuData ; Get local data segment
Mov ES,BX ; Load into segment register
Mov BX,[ES:PrCount] ; Get prompt count
Or BX,BX ; Any prompts yet?
JNZ Okay ; Yes, so continue
Mov AX,BX ; Get low word of return value
Mov DX,BX ; Get high word of return value
Jmp Done ; Exit with return of zero
Okay: Mov [Last],BX ; Store prompt count in local
Mov [NodeSeg],ES ; Store current node pointer
Mov [NodeOfs],Offset ES:HeadOfs - 38
GetDesiredPrompt:
Mov AX,1 ; Specify first param
Push AX ; Put on stack
Call __ParNI ; Get parameter
Add SP,2 ; Realign stack
Mov CX,1 ; Set default value
Or AX,AX ; Specified prompt = 0?
JZ SetActivePrompt ; If so, use default
Cmp AX,[Last] ; Check AX against prompt count
JA SetActivePrompt ; If higher, use default
Mov CX,AX ; Value okay, so use it
SetActivePrompt:
Mov [Active],CX ; Initalize active prompt
GetFlagValues:
Mov AX,2 ; Specify second param
Push AX ; Put on stack
Call __ParNI ; Get parameter
Add SP,2 ; Realign stack
Mov [Flags],AX ; Store flags
GetSetKeyStuff:
Xor AX,AX ; Request element count
Push AX ; Put on stack
Mov AX,3 ; Specify third param
Push AX ; Put on stack
Call __ParInfa ; Get setkey count
Mov [SKCount],AX ; Store key count
SHL AX,1 ; Multiply by by two
Push AX ; Put result on stack
Call __XGrab ; Allocate scan code table
Add SP,6 ; Realign stack
Mov [SKOfs],AX ; Store offset
Mov [SKSeg],DX ; Store segment
Mov CX,[SKCount] ; Set loop value
JCXZ CheckForColor ; If no setkeys, skip next part
GetNextScanCode:
Push CX ; Put element # on stack
Mov AX,3 ; Specify third param
Push AX ; Put on stack
Call __ParNI ; Get scancode
Add SP,2 ; Realign stack
Pop CX ; Restore CX
Mov BX,CX ; Load element # into BX
Dec BX ; Compensate for zero start
SHL BX,1 ; Multiply by two
Add BX,[SKOfs] ; Add offset
Mov ES,[SKSeg] ; Load segment
Mov [Word Ptr ES:BX],AX ; Store scancode
Loop GetNextScanCode ; Do the next one
CheckForColor:
Mov [VideoBase],0B800h ; Default to color
Xor AX,AX ; Clear AX
Mov ES,AX ; Point ES to low memory
Cmp [Word Ptr ES:463h],3D4h ; Color video?
JE VideoTest ; If so, don't change to mono
Mov [VideoBase],0B000h ; Change video base to mono
And [Flags],NOT SnowFlag ; If mono, don't check for snow
Jmp AllocateHotKeys ; Allocate hotkey table
VideoTest:
Mov AH,12h ; EGA/VGA BIOS call
Mov BL,10h ; Set BL to test value
Int 10h ; Call video BIOS
Cmp BL,10h ; Did BL change?
JE AllocateHotKeys ; No, so leave snow flag alone
And [Flags],NOT SnowFlag ; EGA/VGA, set snow flag to false
AllocateHotKeys:
Push [Last] ; Put prompt count on stack
Call __XGrab ; Allocate hotkey table
Add SP,2 ; Realign stack
Mov [TableSeg],DX ; Store segment
Mov [TableOfs],AX ; Store offset
MainLoopSetup:
Push DS ; Save DS
Push SI ; Save SI
Push DI ; Save DI
CLD ; Ensure forward movement
Mov DX,3DAh ; Specify status port for later
Mov CX,[Last] ; Initalize loop register
LES BX,[NodePtr] ; Initialize ES:BX
PromptLoopTop:
Push CX ; Save loop counter
LES BX,[NextPtr] ; Get pointer to next node
Mov AL,[MenuItem.HKeyVal] ; Get hotkey value
LDS SI,[TablePtr] ; Get pointer to hotkey table
Add SI,CX ; Adjust offset
Mov [Byte Ptr SI - 1],AL ; Store hotkey value
LDS SI,[PrPtr] ; Get pointer to prompt
Mov CX,[MenuItem.PrLen] ; Get prompt length
JCXZ PromptLoopBottom ; If length = 0, jump to bottom
Mov AH,[MenuItem.PrAtt] ; Get prompt attribute
Push ES ; Save ES
Mov DI,[MenuItem.PrLoc] ; Get screen location offset
Mov ES,[VideoBase] ; Get screen location segment
PromptRead:
Lodsb ; Get a prompt character
Test [Flags],SnowFlag ; See if snow-check in effect
JZ PromptWrite ; If not, continue
CheckSnow ; Wait for vertical retrace
PromptWrite:
Stosw ; Write character and attribute
Loop PromptRead ; Do next character
Pop ES ; Restore ES
GetHotKeyAttr:
Push ES ; Save ES again
Mov DI,[MenuItem.HKeyLoc] ; Get hotkey location
Inc DI ; Select attribute byte
Mov AL,[MenuItem.HKeyAtt] ; Get hotkey attribute
Mov ES,[VideoBase] ; Get video base segment
Test [Flags],SnowFlag ; See if snow-check in effect
JZ HotKeyAttr ; If not, continue
CheckSnow ; Wait for vertical retrace
HotKeyAttr:
Stosb ; Change attribute byte
Pop ES ; Restore ES
PromptLoopBottom:
Pop CX ; Restore loop counter
Loop PromptLoopTop ; Do next prompt
GetActivePrompt:
LES BX,[NodePtr] ; Get pointer to last node
Mov AX,[Active] ; Load current active item
SearchLinkedList:
LES BX,[NextPtr] ; Get pointer to next item
Cmp AX,[MenuItem.PrNum] ; Found it yet?
JNE SearchLinkedList ; Nope, so keep looking
LightBarStuff:
Push ES ; Save ES
Mov AL,[MenuItem.LBarAtt] ; Get light bar attribute
Mov CX,[MenuItem.PrLen] ; Get prompt length
JCXZ LightBarEnd ; If length = 0, don't bother
Mov DI,[MenuItem.PrLoc] ; Get prompt location
Mov ES,[VideoBase] ; Load video base segment
SetLightBarPtr:
Inc DI ; Locate attribute byte
Test [Flags],SnowFlag ; Check for snow?
JZ WriteLightBar ; If not, continue
CheckSnow ; Wait for vertical retrace
WriteLightBar:
Stosb ; Change attribute
Loop SetLightBarPtr ; Do next byte
LightBarEnd:
Pop ES ; Restore ES
GetLightBarHotKeyAttr:
Push ES ; Save ES again
Mov DI,[MenuItem.HKeyLoc] ; Get hotkey location
Inc DI ; Select attribute byte
Mov AL,[MenuItem.LBHKAtt] ; Get hotkey/lightbar attribute
Mov ES,[VideoBase] ; Get video base segment
Test [Flags],SnowFlag ; See if snow-check in effect
JZ LightBarHotKeyAttr ; If not, continue
CheckSnow ; Wait for vertical retrace
LightBarHotKeyAttr:
Stosb ; Change attribute byte
Pop ES ; Restore ES
BufferStuff:
Test [Flags],SKFlag ; Is setkey flag set?
JNZ MessageStuff ; If so, buffer already current
Push ES ; Save ES
Mov CX,[MenuItem.MsgLen] ; Get message length
JCXZ MessageEnd ; If length = 0, don't bother
Mov DS,[VideoBase] ; Set DS to video RAM
Mov SI,[MenuItem.MsgLoc] ; Get message screen location
LES DI,[BufPtr] ; Get pointer to buffer
Test [Flags],SnowFlag ; Check for snow?
JZ FastBuffer ; If not, use fast method
SlowBuffer:
CheckSnow ; Wait for vertical retrace
Movsw ; Store character and attribute
Loop SlowBuffer ; Do next character
FastBuffer:
Rep Movsw ; Store buffer
Pop ES ; Restore ES
MessageStuff:
And [Flags],NOT SKFlag ; Turn setkey flag off
Push ES ; Save ES
Mov CX,[MenuItem.MsgLen] ; Get message length
JCXZ MessageEnd ; If length = 0, no message
LDS SI,[MsgPtr] ; Get pointer to message
Mov AH,[MenuItem.MsgAtt] ; Get message attribute
Mov DI,[MenuItem.MsgLoc] ; Get message location
Mov ES,[VideoBase] ; Point ES to video RAM
MessageRead:
Lodsb ; Get a message byte
Test [Flags],SnowFlag ; Check for snow?
JZ MessageWrite ; Skip snow check
CheckSnow ; Wait for vertical retrace
MessageWrite:
Stosw ; Write char and attribute
Loop MessageRead ; Get next byte
MessageEnd:
Pop ES ; Restore ES
CheckForHotKey:
Test [Flags],HotFlag ; Hotkey pending?
JZ GetNextKey ; If not, get next key
Test [Flags],ColdFlag ; Hotkeys supposed to act cold?
JNZ GetNextKey ; If so, continue
Jmp ExitWithSelection ; We're finished
GetNextKey:
And [Flags],NOT HotFlag ; Make sure hotflag is off
Mov AH,0 ; BIOS service -- keyboard input
Int 16h ; Get a keystroke
Or AL,AL ; Extended keystroke?
JZ CheckForSetKey ; If so, continue
Mov AH,0 ; Clear scan code -- ASCII in AL
CheckForSetKey:
Mov [ScanCode],AX ; Store most recent scancode
Mov CX,[SKCount] ; Get setkey count
JCXZ CheckEscapeKey ; If 0, no need for table check
Push ES ; Save ES
LES DI,[SetKeys] ; Get pointer to setkey table
Repnz Scasw ; Look for extended scan code
Pop ES ; Restore ES
JNZ CheckEscapeKey ; Not found; check other keys
Or [Flags],KeepFlag ; Turn keep flag on
Jmp ExitWithSelection ; Go back to execute SET KEY
CheckEscapeKey:
Cmp AL,27 ; Escape key?
JNE CheckEnterKey ; If not, check for enter
Mov [Active],0 ; Set return value
Jmp ExitWithSelection ; See if prompts need deallocated
CheckEnterKey:
Cmp AL,13 ; Enter key?
JNE CheckUpLeftArrow ; If not, check arrow keys
Jmp ExitWithSelection ; See if prompts need deallocated
CheckUpLeftArrow:
Mov CX,[MenuItem.Up] ; Get up arrow target
Cmp AX,4800h ; Up arrow key?
JE ProcessUpLeftArrow ; If so, process it
Mov CX,[MenuItem.Left] ; Get left arrow target
Cmp AX,4B00h ; Left arrow key?
JE ProcessUpLeftArrow ; If so, process it
Jmp CheckDownRightArrow ; Check for right or down arrow
ProcessUpLeftArrow:
Or CX,CX ; Default behavior requested?
JZ UpLeftDefault ; If so, go to previous prompt
Cmp CX,[Last] ; Target beyond range?
JA UpLeftDefault ; If so, use default behavior
Jmp GetNewPrompt ; Get new prompt
UpLeftDefault:
Mov CX,[Active] ; Load active prompt
Cmp CX,1 ; First prompt active?
JE UpLeftWrap ; If so, check for wrap
Dec CX ; Decrement active prompt
Jmp UpLeftExit ; Exit
UpLeftWrap:
Test [Flags],WrapFlag ; Wrapping requested?
JZ UpLeftExit ; If not, exit
Mov CX,[Last] ; Wrap to last prompt
UpLeftExit:
Jmp GetNewPrompt ; Get new prompt
CheckDownRightArrow:
Mov CX,[MenuItem.Down] ; Get down arrow target
Cmp AX,5000h ; Down arrow key?
JE ProcessRightDownArrow ; If so, process it
Mov CX,[MenuItem.Right] ; Get right arrow target
Cmp AX,4D00h ; Right arrow key?
JE ProcessRightDownArrow ; If so, process it
Jmp CheckHotKeyTable ; Check hotkey table
ProcessRightDownArrow:
Or CX,CX ; Default behavior requested?
JZ DownRightDefault ; If so, go to previous prompt
Cmp CX,[Last] ; Target beyond range?
JA DownRightDefault ; If so, use default behavior
Jmp GetNewPrompt ; Get new prompt
DownRightDefault:
Mov CX,[Active] ; Load active prompt
Cmp CX,[Last] ; Last? prompt active?
JE DownRightWrap ; If so, check for wrap
Inc CX ; Increment active prompt
Jmp DownRightExit ; Exit
DownRightWrap:
Test [Flags],WrapFlag ; Wrapping requested?
JZ DownRightExit ; If not, exit
Mov CX,1 ; Wrap to last prompt
DownRightExit:
Jmp GetNewPrompt ; Get new prompt
CheckHotKeyTable:
Push ES ; Save ES
Cmp AL,'a' ; Check for lowercase a
JB LoadHotKeyTable ; If below, don't convert
Cmp AL,'z' ; Check for lowercase z
JA LoadHotKeyTable ; If above, don't convert
And AL,0DFh ; Convert to uppercase
LoadHotKeyTable:
LES DI,[TablePtr] ; Get pointer to table
Add DI,[Active] ; Compensate for active prompt
Mov CX,[Last] ; Get last prompt
Cmp CX,[Active] ; At last prompt now?
JE TableWrap ; If so, need to wrap
Sub CX,[Active] ; # of prompts to end
Repne Scasb ; Look for value
JNZ TableWrap ; If not found, wrap to start
Pop ES ; Restore ES
Sub CX,[Last] ; Subtract prompt count
Jmp EvaluateHotKey ; Evaluate hotkey
TableWrap:
LES DI,[TablePtr] ; Get pointer to table
Mov CX,[Active] ; Set CX to active prompt
Repne Scasb ; Look for value
Pop ES ; Restore ES
JNZ KeepSamePrompt ; Invalid key, get another one
Sub CX,[Active] ; Subtract prompt offset
EvaluateHotKey:
Neg CX ; Get absolute value
Or [Flags],HotFlag ; Turn hotflag on
Jmp GetNewPrompt ; Get new prompt
KeepSamePrompt:
Jmp CheckForHotKey ; Discard key and get another
GetNewPrompt:
Cmp CX,[Active] ; Prompt changed?
JE KeepSamePrompt ; If not, keep it
Mov [Active],CX ; Set active prompt
Push ES ; Save ES
Mov AL,[MenuItem.PrAtt] ; Get prompt attribute
Mov CX,[MenuItem.PrLen] ; Get prompt length
JCXZ BarIsDead ; If length = 0, don't bother
Mov DI,[MenuItem.PrLoc] ; Get prompt location
Mov ES,[VideoBase] ; Load video base segment
KillLightBar:
Inc DI ; Locate attribute byte
Test [Flags],SnowFlag ; Check for snow?
JZ ResetPromptAttr ; If not, continue
CheckSnow ; Wait for vertical retrace
ResetPromptAttr:
Stosb ; Change attribute
Loop KillLightBar ; Do next byte
Pop ES ; Restore ES
Push ES ; Save ES again
Mov DI,[MenuItem.HKeyLoc] ; Get hotkey location
Inc DI ; Select attribute byte
Mov AL,[MenuItem.HKeyAtt] ; Get hotkey attribute
Mov ES,[VideoBase] ; Get video base segment
Test [Flags],SnowFlag ; See if snow-check in effect
JZ ResetHotKeyAttr ; If not, continue
CheckSnow ; Wait for vertical retrace
ResetHotKeyAttr:
Stosb ; Change attribute byte
BarIsDead:
Pop ES ; Restore ES
KillMessage:
Push ES ; Save ES
Mov CX,[MenuItem.MsgLen] ; Get message length
JCXZ MessageIsDead ; If length = 0, don't bother
LDS SI,[BufPtr] ; Get pointer to buffer
Mov DI,[MenuItem.MsgLoc] ; Get message screen location
Mov ES,[VideoBase] ; Set DS to video RAM
Test [Flags],SnowFlag ; Check for snow?
JZ QuickDeath ; If not, use fast method
SlowDeath:
CheckSnow ; Wait for vertical retrace
Movsw ; Store character and attribute
Loop SlowDeath ; Do next character
QuickDeath:
Rep Movsw ; Store buffer
MessageIsDead:
Pop ES ; Restore ES
Jmp GetActivePrompt ; Go to top of loop
Done: Push DX ; Put high word on stack
Push AX ; Put low word on stack
Call __RetNL ; Return value to app
Mov SP,BP ; Restore SP
Pop BP ; Restore BP
Ret
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
ExitWithSelection:
Pop DI ; Restore registers
Pop SI
Pop DS
Call Near KillPrompts ; Kill prompts if needed
Push [TableSeg] ; Hotkey table segment on stack
Push [TableOfs] ; HotKey table offset on stack
Call __XFree ; Free allocated RAM
Push [SKSeg] ; Scancode table segment on stack
Push [SKOfs] ; Scancode table offset on stack
Call __XFree ; Free allocated RAM
Mov AX,[Active] ; Set low order word
Mov DX,[ScanCode] ; Set high order word
Jmp Done
KillPrompts:
Test [Flags],KeepFlag ; Supposed to keep prompts?
JZ PromptDeallocSetup ; If not, kill them
RetN ; Near return
PromptDeallocSetup:
LES BX,[NodePtr] ; Get first node pointer
Mov CX,[Last] ; Get loop value
Mov [ES:PrCount],0 ; Reset prompt counter
LES BX,[NextPtr] ; Get pointer to next item
KillAPrompt:
Mov [NodeSeg],ES ; Put ES:BX into local storage --
Mov [NodeOfs],BX ; saves pushing and popping
Push [MenuItem.NextSeg] ; Put next segment on stack
Push [MenuItem.NextOfs] ; Put next offset on stack
Push [MenuItem.PrSeg] ; Put prompt segment on stack
Push [MenuItem.PrOfs] ; Put prompt offset on stack
Call __XFree ; Free memory
LES BX,[NodePtr] ; Restore node pointer
Push [MenuItem.MsgSeg] ; Put message segment on stack
Push [MenuItem.MsgOfs] ; Put message offset on stack
Call __XFree ; Free memory
LES BX,[NodePtr] ; Restore node pointer
Push [MenuItem.BufSeg] ; Put buffer segment on stack
Push [MenuItem.BufOfs] ; Put buffer offset on stack
Call __XFree ; Free memory
LES BX,[NodePtr] ; Restore node pointer
Push ES ; Put node segment on stack
Push BX ; Put node offset on stack
Call __XFree ; Free memory
Add SP,16 ; Realign stack
Pop BX ; Get new node offset
Pop ES ; Get new node segment
Loop KillAPrompt ; Kill next node
RetN ; Near return
Endp __ftMenuTo
Ends _NanFor
End